package dice.sinanya.start;

import net.sf.json.JSONObject;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.nlpcn.commons.lang.util.StringUtil;

import java.io.*;
import java.net.URLDecoder;
import java.util.ArrayList;

import static dice.sinanya.SinaNya.runLevel;
import static dice.sinanya.tools.checkdata.CheckIsNumbers.isNumeric;
import static dice.sinanya.tools.makedata.RandomInt.random;

public class Config implements FindDir {
    private static final Logger logger = LogManager.getLogger(Config.class.getName());
    private final ListenPort listenPort;

    public Config() {
        this.listenPort = new ListenPort();
    }

    public void inputConfig() throws IOException {
        JSONObject configText = makeParam();
        try {
            File confFile = findDir("general.json");
            writeFile(confFile.getPath(), configText.toString());
        } catch (IOException e) {
            logger.error(e.getMessage(), e);
        }
    }

    public int getJavaPort() throws IOException {
        try {
            File confFile = findDir("general.json");
            JSONObject confText = JSONObject.fromObject(readFile(confFile));
            String[] portUrl = confText.getString("post_url").split(":");
            if (portUrl.length == 3 && isNumeric(portUrl[2].trim())) {
                return Integer.parseInt(portUrl[2].trim());
            }
        } catch (IOException e) {
            logger.error(e.getMessage(), e);
        }
        throw new IOException("JavaPort读取失败:\n" + findDir("general.json").getPath());
    }

    public int getServerPort() throws IOException {
        try {
            File confFile = findDir("general.json");
            JSONObject confText = JSONObject.fromObject(readFile(confFile));
            return confText.getInt("port");
        } catch (IOException e) {
            logger.error(e.getMessage(), e);
        }
        throw new IOException("JavaPort读取失败:" + findDir("general.json").getPath());
    }

    public boolean configCantUse() throws IOException {
        try {
            File confFile = findDir("general.json");
            logger.info("general.json目录:\t" + confFile.getPath());
            JSONObject confText = JSONObject.fromObject(readFile(confFile));
            boolean post_url_local = confText.containsKey("post_url") && confText.getString("post_url").split(":").length == 3;
            boolean console = false;
            if (confText.containsKey("show_log_console") && confText.getBoolean("show_log_console")) {
                console = runLevel.equals(RunLevel.DEBUG) || runLevel.equals(RunLevel.PDEBUG);
            } else {
                console = !runLevel.equals(RunLevel.DEBUG) && !runLevel.equals(RunLevel.PDEBUG);
            }
            logger.info("post_url_local:\t" + post_url_local);
            logger.info("console:\t" + console);
            return confText.containsKey("enable_heartbeat") && post_url_local && console;
        } catch (IOException e) {
            logger.error(e.getMessage(), e);
        }
        throw new IOException("配置文件检查失败:" + findDir("general.json").getPath());
    }


    private JSONObject makeParam() throws IOException {
        ListenPort listenPort = new ListenPort();
        int serverPort = getServerPort();
        int javaPort = getJavaPort();
        if (listenPort.listenPort(serverPort) && listenPort.listenPort(javaPort)) {
            serverPort = makeNotUsePort(getServerPort());
            javaPort = makeNotUsePort(getJavaPort());
        }

        JSONObject confText = new JSONObject();
        confText.put("post_url", "http://127.0.0.1:" + javaPort);
        confText.put("port", serverPort);
        confText.put("show_log_console", !runLevel.equals(RunLevel.DEBUG) && !runLevel.equals(RunLevel.PDEBUG));
        confText.put("enable_heartbeat", true);
        confText.put("heartbeat_interval", 5000);
        return confText;
    }

    private int makeNotUsePort(int port) {
        ListenPort listenPort = new ListenPort();
        if (!listenPort.listenPort(port)) {
            return port;
        }
        do {
            port = random(20000, 30000);
        } while (listenPort.listenPort(port));
        return port;
    }

    /**
     * 使用FileWriter类写文本文件
     */
    private void writeFile(String fileName, String text) throws IOException {
        try (FileWriter writer = new FileWriter(fileName, false)) {
            writer.write(text);
            return;
        } catch (IOException e) {
            logger.error(e.getMessage(), e);
        }
        throw new IOException("写入文件:\t" + fileName + "失败");
    }

    private String readFile(File fileName) throws IOException {
        InputStream is = new FileInputStream(fileName);
        BufferedReader in = new BufferedReader(new InputStreamReader(is));
        try {
            StringBuilder buffer = new StringBuilder();
            String line = "";
            while ((line = in.readLine()) != null) {
                buffer.append(line);
            }
            return buffer.toString();
        } catch (IOException e) {
            logger.error(e.getMessage(), e);
        } finally {
            is.close();
            in.close();
        }
        throw new IOException("读取文件:\t" + fileName + "失败");
    }


    @Override
    public File findDir(String fileName) throws IOException {
        File myDir = findMyDir();
        ArrayList<String> pathStr = new ArrayList<>();
        pathStr.add("CoolQ");
        pathStr.add("data");
        pathStr.add("app");
        pathStr.add("io.github.richardchien.coolqhttpapi");
        pathStr.add("config");
        pathStr.add(fileName);
        File conf = new File(URLDecoder.decode(myDir.getPath(), "UTF-8"), StringUtil.joiner(pathStr, File.separator));
        if (conf.exists() && conf.isFile()) {
            return conf;
        }
        throw new IOException("您所查找的文件:\t" + myDir.getPath() + File.separator + StringUtil.joiner(pathStr, File.separator) + "不存在");
    }


}
